package lk.icta.core.entity;

import lk.icta.common.entity.BaseEntity;
import lk.icta.common.entity.President;
import org.hibernate.annotations.IndexColumn;

import javax.persistence.*;
import java.io.Serializable;
import java.util.Date;
import java.util.List;

/**
 * @author Duminda Dharmakeerthi
 */
@Entity
@Table(schema = "ELAND_RAIL")
@NamedQueries({
        @NamedQuery(
                name = "getAllAlienation",
                query = "SELECT a FROM Alienation a "
        ),
        @NamedQuery(
                name = "getAllActiveAlienation",
                query = "SELECT a FROM Alienation a WHERE a.status = 1 AND a.land.gnDivision.dsDivision.id = :dsDivisionId "
        ),
        @NamedQuery(
                name = "getAlienationByLand",
                query = "SELECT a FROM Alienation a WHERE a.land.id = :landId"
        ),
        @NamedQuery(
                name = "getAlienationByHolder",
                query = "SELECT a FROM Alienation a WHERE a.holder.id = :holderId"
        ),
        @NamedQuery(
                name = "getActiveAlienationByLandId",
                query = "SELECT a FROM Alienation a WHERE a.land.id = :landId AND a.status = 1 AND (a.backUpMode IS NULL OR a.backUpMode <> 0)"
        ),
        @NamedQuery(
                name = "getPendingAlienationByLandId",
                query = "SELECT a FROM Alienation a WHERE a.land.id = :landId AND a.status = 2 AND (a.backUpMode IS NULL OR a.backUpMode <> 0) "
        ),
        @NamedQuery(
                name = "getGrantAlienationHistory",
                query = "SELECT a FROM Alienation a WHERE a.root.id = :grantId ORDER BY a.immediateParent.id DESC"
        ),
        @NamedQuery(
                name = "getActiveAlienationByGNDivision",
                query = "SELECT a FROM Alienation a WHERE a.land.gnDivision.id = :id AND a.status = 1"
        ),
        @NamedQuery(
                name = "getChildAlienationNodesByParentId",
                query = "SELECT a FROM Alienation a WHERE a.immediateParent.id = :parentId AND a.status = 1"
        ),
        @NamedQuery(
                name = "getAlienationByAlienationMethod",
                query = "SELECT a FROM Alienation a WHERE a.alienationMethod.id = :alienationMethod " +
                        "AND a.status = 1 AND a.land.gnDivision.dsDivision.id = :dsDivisionId"
        ),
        @NamedQuery(
                name = "getAllAlienationByAlienationMethod",
                query = "SELECT a FROM Alienation a WHERE a.alienationMethod.id = :alienationMethod AND a.status = 1 "
        ),
        @NamedQuery(
                name = "getAlienationByReferenceNo",
                query = "SELECT a FROM Alienation a WHERE a.referenceNo = :referenceNo AND a.status = 1"
        ),
        @NamedQuery(
                name = "getApprovedAlienationByReferenceNo",
                query = "SELECT a FROM Alienation a WHERE a.referenceNo = :referenceNo AND a.status = 1 AND a.approveState=1 AND (a.backUpMode <> 0 OR a.backUpMode IS NULL)"
        ),
        @NamedQuery(
                name = "deleteAlienationFromDatabase",
                query = "DELETE FROM Alienation a WHERE a.id = :alientaionId"
        ),
        @NamedQuery(
                name = "searchApprovedLandPermits",
                query = "SELECT a FROM Alienation a WHERE a.status = 1 AND a.approveState=1 AND (a.backUpMode <> 0 OR a.backUpMode IS NULL) AND a.land.gnDivision.dsDivision.id = :dsDivisionId AND alienationMethod.id =1"
        ),
        @NamedQuery(
                name = "getAlienationFromAlienationMethodAndPendingState",
                query = "SELECT a FROM Alienation a WHERE (1 = :ignoreDS AND a.status = 2 AND (a.backUpMode <> 0 OR a.backUpMode IS NULL)  AND a.alienationMethod.id =:alienationId ) OR" +
                        "(0 = :ignoreDS AND a.status = 2 AND (a.backUpMode <> 0 OR a.backUpMode IS NULL) AND a.alienationMethod.id =:alienationId AND a.land.gnDivision.dsDivision IN (:DSList))"
        )
})
public class Alienation extends BaseEntity {

    public enum State {
        ARCHIVED,   // 0 - State. History Record
        ACTIVE,      // 1 - State. Current Alienation
        PENDING     //2 -pending
    }

    public enum ApproveState {
        REJECTED,   // 0 - State.
        APPROVED,   // 1 - State.
        PENDING,    // 2 - State.
        DATA_ENTRY  // 3 - State.
    }

    public enum BackUpMode {

        INACTIVE /*  0   = backUp the alienation*/
    }

    /**
     * The parent land that is going to be alienated
     */
    @ManyToOne(cascade = {CascadeType.REFRESH})
    @JoinColumn(nullable = true)
    private Land land;

    /**
     * The land list (lots) to be alienated.
     */
    @ManyToMany(fetch = FetchType.EAGER)
    @IndexColumn(name = "INDEX_COL")
    @JoinTable(schema = "ELAND_RAIL")
    private List<Land> landList;

    /**
     * The person who owns the alienation
     */
    @ManyToOne(cascade = {CascadeType.ALL})
    @JoinColumn(nullable = true)
    private Holder holder;

    /**
     * The type of the alienation
     */
    @ManyToOne//(cascade = {CascadeType.REFRESH})
    @JoinColumn(nullable = false)
    private AlienationMethod alienationMethod;

    /**
     * The issue date of the alienation
     */
    @Column(nullable = true)
    @Temporal(value = TemporalType.DATE)
    private Date issueDate;

    /**
     * Reference no of the alienation. (Permit no, Lease no, Grant no, etc.)
     */
    @Column(nullable = false)
    private String referenceNo;

    @Column(nullable = true)
    private String folioNumber;

    @Column(nullable = true)
    @Temporal(value = TemporalType.DATE)
    private Date folioDate;

    @Column(nullable = true)
    private String folioLocation;

    @Column(nullable = true)
    private String successor;

    @Column(nullable = true)
    private String spouse;

    @ManyToOne
    @JoinColumn(name = "permittedUsage", nullable = true)
    private LandUsage permittedUsage;

    @ManyToOne
    @JoinColumn(name = "currentLandUsage", nullable = true)
    private LandUsage currentLandUsage;

    @Column(nullable = true)
    private String landUsageDescription;

    @Column(nullable = true)
    private int alienationPeriod;

    @Column(nullable = true)
    private Double valuation;

    @Column(nullable = true)
    @Temporal(value = TemporalType.DATE)
    private Date paymentDate;

    @Column(nullable = false)
    private State status;

    @Column(nullable = false)
    private ApproveState approveState;

    @Column(nullable = true)
    public String comment;

    @Column(nullable = true)
    public String developmentState;

    @Column(nullable = true)
    public String acquiredDescription;

    @Column(nullable = true)
    public String alienationComment;

    @Column(nullable = true)
    public String encroachmentDescription;

    @Column(nullable = true)
    private int conditionsViolatedOrNot;

    @Column(nullable = true)
    private String conditionsViolationComment;

    @Column(nullable = true)
    private Double rental;

    @Column(nullable = true)
    public Double monthlyInstallment;

    /**
     * To record the root alienation id of Land Grants and Long Term Lease.
     * (in case of transfers)
     */
    @ManyToOne
    @JoinColumn(name = "root", nullable = true)
    private Alienation root;

    /**
     * Immediate Parent alienation Id
     */
    @ManyToOne
    @JoinColumn(name = "immediateParent", nullable = true)
    private Alienation immediateParent;

    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "leaseDetailId", nullable = true)
    private LeaseDetail leaseDetail;

    @OneToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
    @JoinColumn(name = "mortgageId", nullable = true)
    private Mortgage mortgage;

    @ManyToOne
    @JoinColumn(nullable = true)
    private President president;

    @ManyToOne
    @JoinColumn(name = "permitReference", nullable = true)
    private Alienation permitReference;

    @Column(nullable = false)
    private boolean verifiedByBeneficiary;

    @Column(nullable = true)
    private BackUpMode backUpMode;

    @Embedded
    private LifeCycleInfo lifeCycleInfo = new LifeCycleInfo();

    public Land getLand() {
        return land;
    }

    public void setLand(Land land) {
        this.land = land;
    }

    public Holder getHolder() {
        return holder;
    }

    public void setHolder(Holder holder) {
        this.holder = holder;
    }

    public AlienationMethod getAlienationMethod() {
        return alienationMethod;
    }

    public void setAlienationMethod(AlienationMethod alienationMethod) {
        this.alienationMethod = alienationMethod;
    }

    public Date getIssueDate() {
        return issueDate;
    }

    public void setIssueDate(Date issueDate) {
        this.issueDate = issueDate;
    }

    public String getReferenceNo() {
        return referenceNo;
    }

    public void setReferenceNo(String referenceNo) {
        this.referenceNo = referenceNo;
    }

    public String getSuccessor() {
        return successor;
    }

    public void setSuccessor(String successor) {
        this.successor = successor;
    }

    public LandUsage getCurrentLandUsage() {
        return currentLandUsage;
    }

    public void setCurrentLandUsage(LandUsage currentLandUsage) {
        this.currentLandUsage = currentLandUsage;
    }

    public Double getRental() {
        return rental;
    }

    public void setRental(Double rental) {
        this.rental = rental;
    }

    public LeaseDetail getLeaseDetail() {
        return leaseDetail;
    }

    public void setLeaseDetail(LeaseDetail leaseDetail) {
        this.leaseDetail = leaseDetail;
    }

    public State getStatus() {
        return status;
    }

    public void setStatus(State status) {
        this.status = status;
    }

    public Alienation getRoot() {
        return root;
    }

    public void setRoot(Alienation root) {
        this.root = root;
    }

    public Alienation getImmediateParent() {
        return immediateParent;
    }

    public void setImmediateParent(Alienation immediateParent) {
        this.immediateParent = immediateParent;
    }

    public Mortgage getMortgage() {
        return mortgage;
    }

    public void setMortgage(Mortgage mortgage) {
        this.mortgage = mortgage;
    }

    public String getComment() {
        return comment;
    }

    public void setComment(String comment) {
        this.comment = comment;
    }

    public ApproveState getApproveState() {
        return approveState;
    }

    public void setApproveState(ApproveState approveState) {
        this.approveState = approveState;
    }

    public LandUsage getPermittedUsage() {
        return permittedUsage;
    }

    public void setPermittedUsage(LandUsage permittedUsage) {
        this.permittedUsage = permittedUsage;
    }

    public String getSpouse() {
        return spouse;
    }

    public void setSpouse(String spouse) {
        this.spouse = spouse;
    }

    public String getDevelopmentState() {
        return developmentState;
    }

    public void setDevelopmentState(String developmentState) {
        this.developmentState = developmentState;
    }

    public String getAcquiredDescription() {
        return acquiredDescription;
    }

    public void setAcquiredDescription(String acquiredDescription) {
        this.acquiredDescription = acquiredDescription;
    }

    public String getEncroachmentDescription() {
        return encroachmentDescription;
    }

    public void setEncroachmentDescription(String encroachmentDescription) {
        this.encroachmentDescription = encroachmentDescription;
    }

    public Double getMonthlyInstallment() {
        return monthlyInstallment;
    }

    public void setMonthlyInstallment(Double monthlyInstallment) {
        this.monthlyInstallment = monthlyInstallment;
    }

    public String getLandUsageDescription() {
        return landUsageDescription;
    }

    public void setLandUsageDescription(String landUsageDescription) {
        this.landUsageDescription = landUsageDescription;
    }

    public LifeCycleInfo getLifeCycleInfo() {
        return lifeCycleInfo;
    }

    public void setLifeCycleInfo(LifeCycleInfo lifeCycleInfo) {
        this.lifeCycleInfo = lifeCycleInfo;
    }

    public String getAlienationComment() {
        return alienationComment;
    }

    public void setAlienationComment(String alienationComment) {
        this.alienationComment = alienationComment;
    }

    public String getFolioNumber() {
        return folioNumber;
    }

    public void setFolioNumber(String folioNumber) {
        this.folioNumber = folioNumber;
    }

    public Date getFolioDate() {
        return folioDate;
    }

    public void setFolioDate(Date folioDate) {
        this.folioDate = folioDate;
    }

    public String getFolioLocation() {
        return folioLocation;
    }

    public void setFolioLocation(String folioLocation) {
        this.folioLocation = folioLocation;
    }

    /**
     * conditionsViolatedOrNot 0 - No., 1 - Yes
     */
    public int getConditionsViolatedOrNot() {
        return conditionsViolatedOrNot;
    }

    public void setConditionsViolatedOrNot(int conditionsViolatedOrNot) {
        this.conditionsViolatedOrNot = conditionsViolatedOrNot;
    }

    public String getConditionsViolationComment() {
        return conditionsViolationComment;
    }

    public void setConditionsViolationComment(String conditionsViolationComment) {
        this.conditionsViolationComment = conditionsViolationComment;
    }

    public int getAlienationPeriod() {
        return alienationPeriod;
    }

    public void setAlienationPeriod(int alienationPeriod) {
        this.alienationPeriod = alienationPeriod;
    }

    public Double getValuation() {
        return valuation;
    }

    public void setValuation(Double valuation) {
        this.valuation = valuation;
    }

    public Date getPaymentDate() {
        return paymentDate;
    }

    public void setPaymentDate(Date paymentDate) {
        this.paymentDate = paymentDate;
    }

    public List<Land> getLandList() {
        return landList;
    }

    public void setLandList(List<Land> landList) {
        this.landList = landList;
    }

    public President getPresident() {
        return president;
    }

    public void setPresident(President president) {
        this.president = president;
    }

    public Alienation getPermitReference() {
        return permitReference;
    }

    public void setPermitReference(Alienation permitReference) {
        this.permitReference = permitReference;
    }

    public boolean isVerifiedByBeneficiary() {
        return verifiedByBeneficiary;
    }

    public void setVerifiedByBeneficiary(boolean verifiedByBeneficiary) {
        this.verifiedByBeneficiary = verifiedByBeneficiary;
    }

    public BackUpMode getBackUpMode() {
        return backUpMode;
    }

    public void setBackUpMode(BackUpMode backUpMode) {
        this.backUpMode = backUpMode;
    }


}
